package messageOrderingModule;

import generalObjects.GroupView;
import generalObjects.LayerAccess;

import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.server.ServerNotActiveException;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicBoolean;

import javax.swing.event.ChangeListener;

import communicationModule.MessageObject;
import communicationModule.SendResult;

/**
 * The layer of the GCom stack that is responsible for sorting messages
 * according to the sort algorithm chosen by the creator of the group. These are
 * either causal ordering or unordered.
 * 
 */
public class MOMLayerAccess implements LayerAccess {

    private LayerAccess lowerLayer;
    private final Properties sessionProp;
    private final CausalAlgorithm cOrder;
    private final AtomicBoolean stateChanged;
    private final ChangeListener orderingHoldbackUpdater;

    public MOMLayerAccess(final Properties sessionProp, final GroupView gView,
            ChangeListener orderingHoldbackUpdater) {
        this.sessionProp = sessionProp;
        this.orderingHoldbackUpdater = orderingHoldbackUpdater;
        this.stateChanged = new AtomicBoolean(false);
        cOrder = new CausalAlgorithm(gView, stateChanged);
    }

    @Override
    public void setLowerLayer(final LayerAccess layer) {
        lowerLayer = layer;
    }

    @Override
    public List<SendResult> process(final List<MessageObject> mOList)
            throws RemoteException, NotBoundException, ServerNotActiveException {
        List<SendResult> results = lowerLayer.process(mOList);
        if (results != null) {
            if (sessionProp.getProperty("ordering").equals("true")) {
                results = cOrder.getDeliverables(results);
                if (orderingHoldbackUpdater != null && stateChanged.get()) {
                    orderingHoldbackUpdater.stateChanged(null);
                    stateChanged.compareAndSet(true, false);
                }
            }
        }
        return results;
    }

    public MessageObject[] getHoldbackQueue() {
        return cOrder.getHoldbackQueue();
    }

}